package nape.phys;
import zpp_nape.Config;
import zpp_nape.Const;
import zpp_nape.util.Flags;
import DummyNapeMain;
import zpp_nape.util.Math;
import zpp_nape.util.Names;
import zpp_nape.util.Pool;
import zpp_nape.util.Lists;
import zpp_nape.shape.Circle;
import zpp_nape.shape.Edge;
import zpp_nape.space.Space;
import zpp_nape.shape.Polygon;
import zpp_nape.shape.Shape;
import zpp_nape.phys.FeatureMix;
import zpp_nape.phys.FluidProperties;
import zpp_nape.phys.Material;
import zpp_nape.phys.Body;
import zpp_nape.geom.AABB;
import zpp_nape.geom.Distance;
import zpp_nape.geom.Mat23;
import zpp_nape.geom.Vec2;
import zpp_nape.geom.VecMath;
import zpp_nape.geom.Collide;
import zpp_nape.dynamics.Arbiter;
import zpp_nape.dynamics.Contact;
import zpp_nape.dynamics.InteractionFilter;
import zpp_nape.constraint.Constraint;
import zpp_nape.dynamics.SpaceArbiterList;
import zpp_nape.constraint.Matrices;
import zpp_nape.constraint.PivotJoint;
import zpp_nape.constraint.WeldJoint;
import nape.util.Flags;
import nape.util.Lists;
import nape.util.Debug;
import nape.space.Space;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.shape.Edge;
import nape.shape.Shape;
import nape.phys.FluidProperties;
import nape.phys.Material;
import nape.geom.AABB;
import nape.geom.Geom;
import nape.geom.Mat23;
import nape.geom.Vec2;
import nape.dynamics.Contact;
import nape.dynamics.Arbiter;
import nape.dynamics.InteractionFilter;
#if swc@:keep#end class MassMode{
    public function new(){
        if(!ZPP_Flags.internal)throw "Error: Cannot instantiate "+"MassMode"+" derp!";
    }
    @:keep inline public function toString(){
        if(false)return "";
        
        else if(this==DEFAULT)return"DEFAULT";
        else if(this==FIXED)return"FIXED";
        else return "";
    }
    public static var DEFAULT(flibget_DEFAULT,never):MassMode;
    inline static function flibget_DEFAULT(){
        if(ZPP_Flags.MassMode_DEFAULT==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.MassMode_DEFAULT=new MassMode();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.MassMode_DEFAULT;
    }
    public static var FIXED(flibget_FIXED,never):MassMode;
    inline static function flibget_FIXED(){
        if(ZPP_Flags.MassMode_FIXED==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.MassMode_FIXED=new MassMode();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.MassMode_FIXED;
    }
}
#if swc@:keep#end class GravMassMode{
    public function new(){
        if(!ZPP_Flags.internal)throw "Error: Cannot instantiate "+"GravMassMode"+" derp!";
    }
    @:keep inline public function toString(){
        if(false)return "";
        
        else if(this==DEFAULT)return"DEFAULT";
        else if(this==FIXED)return"FIXED";
        else if(this==SCALED)return"SCALED";
        else return "";
    }
    public static var DEFAULT(flibget_DEFAULT,never):GravMassMode;
    inline static function flibget_DEFAULT(){
        if(ZPP_Flags.GravMassMode_DEFAULT==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.GravMassMode_DEFAULT=new GravMassMode();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.GravMassMode_DEFAULT;
    }
    public static var FIXED(flibget_FIXED,never):GravMassMode;
    inline static function flibget_FIXED(){
        if(ZPP_Flags.GravMassMode_FIXED==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.GravMassMode_FIXED=new GravMassMode();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.GravMassMode_FIXED;
    }
    public static var SCALED(flibget_SCALED,never):GravMassMode;
    inline static function flibget_SCALED(){
        if(ZPP_Flags.GravMassMode_SCALED==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.GravMassMode_SCALED=new GravMassMode();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.GravMassMode_SCALED;
    }
}
#if swc@:keep#end class BodyType{
    public function new(){
        if(!ZPP_Flags.internal)throw "Error: Cannot instantiate "+"BodyType"+" derp!";
    }
    @:keep inline public function toString(){
        if(false)return "";
        
        else if(this==DYNAMIC)return"DYNAMIC";
        else if(this==KINEMATIC)return"KINEMATIC";
        else if(this==STATIC)return"STATIC";
        else return "";
    }
    public static var STATIC(flibget_STATIC,never):BodyType;
    inline static function flibget_STATIC(){
        if(ZPP_Flags.BodyType_STATIC==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.BodyType_STATIC=new BodyType();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.BodyType_STATIC;
    }
    public static var DYNAMIC(flibget_DYNAMIC,never):BodyType;
    inline static function flibget_DYNAMIC(){
        if(ZPP_Flags.BodyType_DYNAMIC==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.BodyType_DYNAMIC=new BodyType();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.BodyType_DYNAMIC;
    }
    public static var KINEMATIC(flibget_KINEMATIC,never):BodyType;
    inline static function flibget_KINEMATIC(){
        if(ZPP_Flags.BodyType_KINEMATIC==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.BodyType_KINEMATIC=new BodyType();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.BodyType_KINEMATIC;
    }
}
#if swc@:keep#end class InertiaMode{
    public function new(){
        if(!ZPP_Flags.internal)throw "Error: Cannot instantiate "+"InertiaMode"+" derp!";
    }
    @:keep inline public function toString(){
        if(false)return "";
        
        else if(this==DEFAULT)return"DEFAULT";
        else if(this==FIXED)return"FIXED";
        else return "";
    }
    public static var DEFAULT(flibget_DEFAULT,never):InertiaMode;
    inline static function flibget_DEFAULT(){
        if(ZPP_Flags.InertiaMode_DEFAULT==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.InertiaMode_DEFAULT=new InertiaMode();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.InertiaMode_DEFAULT;
    }
    public static var FIXED(flibget_FIXED,never):InertiaMode;
    inline static function flibget_FIXED(){
        if(ZPP_Flags.InertiaMode_FIXED==null){
            ZPP_Flags.internal=true;
            ZPP_Flags.InertiaMode_FIXED=new InertiaMode();
            ZPP_Flags.internal=false;
        }
        return ZPP_Flags.InertiaMode_FIXED;
    }
}
#if swc@:keep#end class BodyList{
    public var zpp_inner:ZPP_BodyList;
    public var length(flibget_length,never):Int;
    #if true inline function flibget_length(){
        zpp_inner.valmod();
        if(zpp_inner.zip_length){
            zpp_inner.zip_length=false;
            if(false){
                zpp_inner.user_length=0;
                {
                    var cx_ite=zpp_inner.inner.begin();
                    while(cx_ite!=null){
                        var i=cx_ite.elem();
                        if(true)zpp_inner.user_length++;
                        cx_ite=cx_ite.next;
                    }
                };
            }
            else zpp_inner.user_length=zpp_inner.length;
        }
        return zpp_inner.user_length;
    }
    #else inline function flibget_length(){
        return zpp_gl();
    }
    public function zpp_gl(){
        zpp_inner.valmod();
        if(zpp_inner.zip_length){
            zpp_inner.zip_length=false;
            if(false){
                zpp_inner.user_length=0;
                {
                    var cx_ite=zpp_inner.inner.begin();
                    while(cx_ite!=null){
                        var i=cx_ite.elem();
                        if(true)zpp_inner.user_length++;
                        cx_ite=cx_ite.next;
                    }
                };
            }
            else zpp_inner.user_length=zpp_inner.length;
        }
        return zpp_inner.user_length;
    }
    public function zpp_vm(){
        zpp_inner.valmod();
    }
    #end#if swc@:keep#end public static inline function fromArray(array:#if flash9 Array<Dynamic>#else Array<Body>#end){
        var ret=new BodyList();
        for(i in array){
            #if flash9 if(!Std.is(i,Body))throw "Error: Array contains non "+"Body"+" types.";
            #end ret.push(i);
        }
        return ret;
    }
    #if flash9#if swc@:keep#end public static inline function fromVector(vector:flash.Vector<Body>){
        var ret=new BodyList();
        for(i in vector)ret.push(i);
        return ret;
    }
    #end#if swc@:keep#end public inline function at(index:Int):Body{
        #if true zpp_inner.valmod();
        #else zpp_vm();
        #end if(index<0||index>=length)throw "Error: Index out of bounds";
        if(zpp_inner.reverse_flag)index=(length-1-index);
        if(!false){
            if(index<zpp_inner.at_index||zpp_inner.at_ite==null){
                zpp_inner.at_index=index;
                zpp_inner.at_ite=zpp_inner.inner.iterator_at(index);
            }
            else{
                while(zpp_inner.at_index!=index){
                    zpp_inner.at_index++;
                    zpp_inner.at_ite=zpp_inner.at_ite.next;
                }
            }
        }
        else{
            if(index<zpp_inner.at_index||zpp_inner.at_ite==null){
                zpp_inner.at_index=0;
                zpp_inner.at_ite=zpp_inner.inner.begin();
                while(true){
                    var x=zpp_inner.at_ite.elem();
                    if(true)break;
                    zpp_inner.at_ite=zpp_inner.at_ite.next;
                }
            }
            while(zpp_inner.at_index!=index){
                zpp_inner.at_index++;
                zpp_inner.at_ite=zpp_inner.at_ite.next;
                while(true){
                    var x=zpp_inner.at_ite.elem();
                    if(true)break;
                    zpp_inner.at_ite=zpp_inner.at_ite.next;
                }
            }
        }
        return zpp_inner.at_ite.elem().outer;
    }
    #if swc@:keep#end public inline function push(obj:Body){
        if(zpp_inner.immutable)throw "Error: "+"Body"+"List is immutable";
        zpp_inner.modify_test();
        #if true zpp_inner.valmod();
        #else zpp_vm();
        #end var cont=if(zpp_inner.adder!=null)zpp_inner.adder(obj)else true;
        if(cont){
            if(zpp_inner.reverse_flag)zpp_inner.inner.add(obj.zpp_inner);
            else{
                if(zpp_inner.push_ite==null)zpp_inner.push_ite=empty()?null:zpp_inner.inner.iterator_at(length-1);
                zpp_inner.push_ite=zpp_inner.inner.insert(zpp_inner.push_ite,obj.zpp_inner);
            }
            zpp_inner.invalidate();
            if(zpp_inner.post_adder!=null)zpp_inner.post_adder(obj);
        }
        return cont;
    }
    #if swc@:keep#end public inline function unshift(obj:Body){
        if(zpp_inner.immutable)throw "Error: "+"Body"+"List is immutable";
        zpp_inner.modify_test();
        #if true zpp_inner.valmod();
        #else zpp_vm();
        #end var cont=if(zpp_inner.adder!=null)zpp_inner.adder(obj)else true;
        if(cont){
            if(zpp_inner.reverse_flag){
                if(zpp_inner.push_ite==null)zpp_inner.push_ite=empty()?null:zpp_inner.inner.iterator_at(length-1);
                zpp_inner.push_ite=zpp_inner.inner.insert(zpp_inner.push_ite,obj.zpp_inner);
            }
            else zpp_inner.inner.add(obj.zpp_inner);
            zpp_inner.invalidate();
            if(zpp_inner.post_adder!=null)zpp_inner.post_adder(obj);
        }
        return cont;
    }
    #if swc@:keep#end public inline function pop():Body{
        if(zpp_inner.immutable)throw "Error: "+"Body"+"List is immutable";
        zpp_inner.modify_test();
        if(empty())throw "Error: Cannot remove from empty list";
        #if true zpp_inner.valmod();
        #else zpp_vm();
        #end var ret=null;
        if(zpp_inner.reverse_flag){
            ret=zpp_inner.inner.front();
            var retx=ret.outer;
            if(zpp_inner.subber!=null)zpp_inner.subber(retx);
            zpp_inner.inner.pop();
        }
        else{
            if(zpp_inner.at_ite!=null&&zpp_inner.at_ite.next==null)zpp_inner.at_ite=null;
            var ite=length==1?null:zpp_inner.inner.iterator_at(length-2);
            ret=ite==null?zpp_inner.inner.front():ite.next.elem();
            var retx=ret.outer;
            if(zpp_inner.subber!=null)zpp_inner.subber(retx);
            zpp_inner.inner.erase(ite);
        }
        zpp_inner.invalidate();
        var retx=ret.outer;
        return retx;
    }
    #if swc@:keep#end public inline function shift():Body{
        if(zpp_inner.immutable)throw "Error: "+"Body"+"List is immutable";
        zpp_inner.modify_test();
        if(empty())throw "Error: Cannot remove from empty list";
        #if true zpp_inner.valmod();
        #else zpp_vm();
        #end var ret=null;
        if(zpp_inner.reverse_flag){
            if(zpp_inner.at_ite!=null&&zpp_inner.at_ite.next==null)zpp_inner.at_ite=null;
            var ite=length==1?null:zpp_inner.inner.iterator_at(length-2);
            ret=ite==null?zpp_inner.inner.front():ite.next.elem();
            var retx=ret.outer;
            if(zpp_inner.subber!=null)zpp_inner.subber(retx);
            zpp_inner.inner.erase(ite);
        }
        else{
            ret=zpp_inner.inner.front();
            var retx=ret.outer;
            if(zpp_inner.subber!=null)zpp_inner.subber(retx);
            zpp_inner.inner.pop();
        }
        zpp_inner.invalidate();
        var retx=ret.outer;
        return retx;
    }
    #if swc@:keep#end public inline function add(obj:Body)return if(zpp_inner.reverse_flag)push(obj)else unshift(obj)#if swc@:keep#end public inline function remove(obj:Body):Bool{
        if(zpp_inner.immutable)throw "Error: "+"Body"+"List is immutable";
        zpp_inner.modify_test();
        #if true zpp_inner.valmod();
        #else zpp_vm();
        #end var ret=({
            var ret=false;
            {
                var cx_ite=zpp_inner.inner.begin();
                while(cx_ite!=null){
                    var x=cx_ite.elem();
                    {
                        if(x==obj.zpp_inner){
                            ret=true;
                            break;
                        }
                    };
                    cx_ite=cx_ite.next;
                }
            };
            ret;
        });
        if(ret){
            if(zpp_inner.subber!=null)zpp_inner.subber(obj);
            zpp_inner.inner.remove(obj.zpp_inner);
            zpp_inner.invalidate();
        }
        return ret;
    }
    #if swc@:keep#end public inline function empty(){
        #if true if(false)return length==0;
        else return zpp_inner.inner.empty();
        #else return length==0;
        #end
    }
    #if swc@:keep#end public inline function iterator(){
        #if true zpp_inner.valmod();
        #else zpp_vm();
        #end if(zpp_inner.iterators==null)zpp_inner.iterators=new ZNPList_BodyIterator();
        return BodyIterator.get(this);
    }
    #if swc@:keep#end public inline function copy(?deep:Bool=false){
        var ret=new BodyList();
        for(i in this)ret.push(deep?{
            throw "Error: "+"Body"+" is not a copyable type";
        }
        :i);
        return ret;
    }
    public function new(){
        zpp_inner=new ZPP_BodyList();
        zpp_inner.outer=this;
    }
    @:keep public inline function toString(){
        var ret="[";
        var fst=true;
        for(i in this){
            if(!fst)ret+=",";
            ret+=i.toString();
            fst=false;
        }
        return ret+"]";
    }
}
#if swc@:keep#end class BodyIterator{
    public var zpp_inner:BodyList;
    public var zpp_i:Int;
    public var zpp_critical:Bool;
    public static var zpp_pool:BodyIterator;
    public var zpp_next:BodyIterator;
    public function new(){
        if(!ZPP_BodyList.internal)throw "Error: Cannot instantiate "+"Body"+"Iterator derp!";
    }
    public static inline function get(list:BodyList){
        var ret=if(zpp_pool==null){
            ZPP_BodyList.internal=true;
            var ret=new BodyIterator();
            ZPP_BodyList.internal=false;
            ret;
        }
        else{
            var r=zpp_pool;
            zpp_pool=r.zpp_next;
            r;
        }
        ret.zpp_i=0;
        ret.zpp_inner=list;
        ret.zpp_critical=false;
        list.zpp_inner.iterators.add(ret);
        return ret;
    }
    #if swc@:keep#end public inline function hasNext(){
        #if true zpp_inner.zpp_inner.valmod();
        #else zpp_inner.zpp_vm();
        #end var length=zpp_inner.length;
        zpp_critical=true;
        if(zpp_i<length){
            return true;
        }
        else{
            zpp_next=zpp_pool;
            zpp_pool=this;
            zpp_inner.zpp_inner.iterators.remove(this);
            return false;
        }
    }
    #if swc@:keep#end public inline function next(){
        zpp_critical=false;
        return zpp_inner.at(zpp_i++);
    }
}
#if swc@:keep#end class Body{
    public var zpp_inner:ZPP_Body;
    public var id(flibget_id,never):Int;
    inline function flibget_id()return zpp_inner.id public var type(flibget_type,flibset_type):BodyType;
    inline function flibget_type()return[BodyType.STATIC,BodyType.DYNAMIC,BodyType.KINEMATIC][zpp_inner.type]inline function flibset_type(type:BodyType){
        if(this.type!=type){
            if(type==null)throw "Error: Cannot use null BodyType";
            if(type==BodyType.KINEMATIC){
                {
                    zpp_inner.kinvelx=0;
                    zpp_inner.kinvely=0;
                    {
                        #if NAPE_ASSERT var res={
                            !({
                                #if flash9 var ret:Bool=untyped __global__["isNaN"](zpp_inner.kinvelx);
                                ret;
                                #else Math.isNaN(zpp_inner.kinvelx);
                                #end
                            });
                        };
                        if(!res)throw "assert("+"!assert_isNaN(zpp_inner.kinvelx)"+") :: "+("vec_set(in n: "+"zpp_inner.kinvel"+",in x: "+"0"+",in y: "+"0"+")");
                        #end
                    };
                    {
                        #if NAPE_ASSERT var res={
                            !({
                                #if flash9 var ret:Bool=untyped __global__["isNaN"](zpp_inner.kinvely);
                                ret;
                                #else Math.isNaN(zpp_inner.kinvely);
                                #end
                            });
                        };
                        if(!res)throw "assert("+"!assert_isNaN(zpp_inner.kinvely)"+") :: "+("vec_set(in n: "+"zpp_inner.kinvel"+",in x: "+"0"+",in y: "+"0"+")");
                        #end
                    };
                };
                zpp_inner.kinangvel=0;
            }
            else if(type==BodyType.STATIC){
                {
                    zpp_inner.velx=0;
                    zpp_inner.vely=0;
                    {
                        #if NAPE_ASSERT var res={
                            !({
                                #if flash9 var ret:Bool=untyped __global__["isNaN"](zpp_inner.velx);
                                ret;
                                #else Math.isNaN(zpp_inner.velx);
                                #end
                            });
                        };
                        if(!res)throw "assert("+"!assert_isNaN(zpp_inner.velx)"+") :: "+("vec_set(in n: "+"zpp_inner.vel"+",in x: "+"0"+",in y: "+"0"+")");
                        #end
                    };
                    {
                        #if NAPE_ASSERT var res={
                            !({
                                #if flash9 var ret:Bool=untyped __global__["isNaN"](zpp_inner.vely);
                                ret;
                                #else Math.isNaN(zpp_inner.vely);
                                #end
                            });
                        };
                        if(!res)throw "assert("+"!assert_isNaN(zpp_inner.vely)"+") :: "+("vec_set(in n: "+"zpp_inner.vel"+",in x: "+"0"+",in y: "+"0"+")");
                        #end
                    };
                };
                zpp_inner.angvel=0;
            }
            var ptype=this.zpp_inner.type;
            zpp_inner.type=type==BodyType.DYNAMIC?ZPP_Flags.id_BodyType_DYNAMIC:type==BodyType.KINEMATIC?ZPP_Flags.id_BodyType_KINEMATIC:ZPP_Flags.id_BodyType_STATIC;
            if(zpp_inner.space!=null)zpp_inner.space.transmitType(zpp_inner,ptype,zpp_inner.type);
            zpp_inner.invalidate_type();
        }
        return this.type;
    }
    #if swc@:keep#end public inline function isStatic()return zpp_inner.isStatic()#if swc@:keep#end public inline function isDynamic()return zpp_inner.isDynamic()#if swc@:keep#end public inline function isKinematic()return zpp_inner.isKinematic()public var userData:Dynamic;
    public var shapes(flibget_shapes,never):ShapeList;
    inline function flibget_shapes()return zpp_inner.wrap_shapes public var space(flibget_space,flibset_space):Space;
    inline function flibget_space(){
        if(zpp_inner.space==null)return null;
        else return zpp_inner.space.outer;
    }
    inline function flibset_space(space:Space){
        if(this.space!=space){
            if(zpp_inner.space!=null)zpp_inner.space.removeBody(zpp_inner);
            if(space!=null){
                zpp_inner.space=space.zpp_inner;
                zpp_inner.space.addBody(zpp_inner);
            }
            else zpp_inner.space=null;
        }
        return space;
    }
    public var arbiters(flibget_arbiters,never):ArbiterList;
    inline function flibget_arbiters(){
        if(zpp_inner.wrap_arbiters==null)zpp_inner.wrap_arbiters=ZPP_ArbiterList.get(zpp_inner.arbiters,true);
        return zpp_inner.wrap_arbiters;
    }
    public var isSleeping(flibget_isSleeping,never):Bool;
    inline function flibget_isSleeping(){
        if(zpp_inner.space==null)throw "Error: isSleeping makes no sense if the object is not contained within a Space";
        return zpp_inner.sleeping;
    }
    public function new(?type:BodyType,?position:Vec2){
        zpp_inner=new ZPP_Body();
        zpp_inner.outer=this;
        if(position!=null){
            zpp_inner.posx=position.x;
            zpp_inner.posy=position.y;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](zpp_inner.posx);
                        ret;
                        #else Math.isNaN(zpp_inner.posx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(zpp_inner.posx)"+") :: "+("vec_set(in n: "+"zpp_inner.pos"+",in x: "+"position.x"+",in y: "+"position.y"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](zpp_inner.posy);
                        ret;
                        #else Math.isNaN(zpp_inner.posy);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(zpp_inner.posy)"+") :: "+("vec_set(in n: "+"zpp_inner.pos"+",in x: "+"position.x"+",in y: "+"position.y"+")");
                #end
            };
        };
        else{
            zpp_inner.posx=0;
            zpp_inner.posy=0;
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](zpp_inner.posx);
                        ret;
                        #else Math.isNaN(zpp_inner.posx);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(zpp_inner.posx)"+") :: "+("vec_set(in n: "+"zpp_inner.pos"+",in x: "+"0"+",in y: "+"0"+")");
                #end
            };
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](zpp_inner.posy);
                        ret;
                        #else Math.isNaN(zpp_inner.posy);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(zpp_inner.posy)"+") :: "+("vec_set(in n: "+"zpp_inner.pos"+",in x: "+"0"+",in y: "+"0"+")");
                #end
            };
        };
        this.type=type==null?BodyType.DYNAMIC:type;
    }
    #if swc@:keep#end public inline function copy(){
        return zpp_inner.copy();
    }
    public var position(flibget_position,flibset_position):Vec2;
    inline function flibget_position(){
        if(zpp_inner.wrap_pos==null)zpp_inner.setupPosition();
        return zpp_inner.wrap_pos;
    }
    inline function flibset_position(position:Vec2)return this.position.set(position)public var velocity(flibget_velocity,flibset_velocity):Vec2;
    inline function flibget_velocity(){
        if(zpp_inner.wrap_vel==null)zpp_inner.setupVelocity();
        return zpp_inner.wrap_vel;
    }
    inline function flibset_velocity(velocity:Vec2)return this.velocity.set(velocity)public var force(flibget_force,flibset_force):Vec2;
    inline function flibget_force(){
        if(zpp_inner.wrap_force==null)zpp_inner.setupForce();
        return zpp_inner.wrap_force;
    }
    inline function flibset_force(force:Vec2)return this.force.set(force)public var rotation(flibget_rotation,flibset_rotation):Float;
    inline function flibget_rotation()return zpp_inner.rot inline function flibset_rotation(rotation:Float):Float{
        if(isStatic()&&zpp_inner.space!=null)throw "Error: Static objects cannot be rotated once inside a Space";
        if(this.rotation!=rotation){
            if(({
                #if flash9 var ret:Bool=untyped __global__["isNaN"](rotation);
                ret;
                #else Math.isNaN(rotation);
                #end
            }))throw "Error: Body::rotation cannot be NaN";
            zpp_inner.rot=rotation;
            zpp_inner.invalidate_rot();
            zpp_inner.wakeall();
        }
        return this.rotation;
    }
    public var angularVel(flibget_angularVel,flibset_angularVel):Float;
    inline function flibget_angularVel(){
        if(isKinematic())return zpp_inner.kinangvel;
        else return zpp_inner.angvel;
    }
    inline function flibset_angularVel(angularVel:Float):Float{
        if(this.angularVel!=angularVel){
            if(({
                #if flash9 var ret:Bool=untyped __global__["isNaN"](angularVel);
                ret;
                #else Math.isNaN(angularVel);
                #end
            }))throw "Error: Body::angularVel cannot be NaN";
            if(isKinematic())zpp_inner.kinangvel=angularVel;
            else zpp_inner.angvel=angularVel;
            if(!isStatic())zpp_inner.invalidate_wake();
        }
        return this.angularVel;
    }
    public var torque(flibget_torque,flibset_torque):Float;
    inline function flibget_torque()return zpp_inner.torque inline function flibset_torque(torque:Float):Float{
        if(({
            #if flash9 var ret:Bool=untyped __global__["isNaN"](torque);
            ret;
            #else Math.isNaN(torque);
            #end
        }))throw "Error: Body::torqur cannot be NaN";
        if(this.torque!=torque){
            zpp_inner.torque=torque;
            if(isDynamic())zpp_inner.invalidate_wake();
        }
        return this.torque;
    }
    public var bounds(flibget_bounds,never):AABB;
    inline function flibget_bounds(){
        if(zpp_inner.shapes.empty())throw "Error: Body bounds only makes sense if it contains shapes";
        return zpp_inner.aabb.wrapper();
    }
    public var massMode(flibget_massMode,flibset_massMode):MassMode;
    inline function flibget_massMode(){
        return[MassMode.DEFAULT,MassMode.FIXED][zpp_inner.massMode];
    }
    inline function flibset_massMode(massMode:MassMode){
        if(massMode==null)throw "Error: cannot use null massMode";
        zpp_inner.massMode=massMode==MassMode.DEFAULT?ZPP_Flags.id_MassMode_DEFAULT:ZPP_Flags.id_MassMode_FIXED;
        zpp_inner.invalidate_mass();
        return this.massMode;
    }
    public var mass(flibget_mass,flibset_mass):Float;
    inline function flibget_mass(){
        zpp_inner.validate_mass();
        if(zpp_inner.massMode==ZPP_Flags.id_MassMode_DEFAULT&&zpp_inner.shapes.empty())throw "Error: Given current mass mode, Body::mass only makes sense if it contains shapes";
        return zpp_inner.cmass;
    }
    inline function flibset_mass(mass:Float){
        if(({
            #if flash9 var ret:Bool=untyped __global__["isNaN"](mass);
            ret;
            #else Math.isNaN(mass);
            #end
        }))throw "Error: Mass cannot be NaN";
        if(mass<=0)throw "Error: Mass must be strictly positive";
        zpp_inner.massMode=ZPP_Flags.id_MassMode_FIXED;
        zpp_inner.cmass=mass;
        zpp_inner.invalidate_mass();
        return zpp_inner.cmass;
    }
    public var gravMassMode(flibget_gravMassMode,flibset_gravMassMode):GravMassMode;
    inline function flibget_gravMassMode(){
        return[GravMassMode.DEFAULT,GravMassMode.FIXED,GravMassMode.SCALED][zpp_inner.massMode];
    }
    inline function flibset_gravMassMode(gravMassMode:GravMassMode){
        if(gravMassMode==null)throw "Error: Cannot use null gravMassMode";
        zpp_inner.gravMassMode=gravMassMode==GravMassMode.SCALED?ZPP_Flags.id_GravMassMode_SCALED:gravMassMode==GravMassMode.DEFAULT?ZPP_Flags.id_GravMassMode_DEFAULT:ZPP_Flags.id_GravMassMode_FIXED;
        zpp_inner.invalidate_gravMass();
        return this.gravMassMode;
    }
    public var gravMass(flibget_gravMass,flibset_gravMass):Float;
    inline function flibget_gravMass(){
        zpp_inner.validate_gravMass();
        if(zpp_inner.shapes.empty()){
            if(zpp_inner.massMode==ZPP_Flags.id_MassMode_DEFAULT&&zpp_inner.gravMassMode!=ZPP_Flags.id_GravMassMode_FIXED)throw "Error: Given current mass/gravMass modes; Body::gravMass only makes sense if it contains Shapes";
        }
        return zpp_inner.gravMass;
    }
    inline function flibset_gravMass(gravMass:Float){
        if(({
            #if flash9 var ret:Bool=untyped __global__["isNaN"](gravMass);
            ret;
            #else Math.isNaN(gravMass);
            #end
        }))throw "Error: gravMass cannot be NaN";
        zpp_inner.gravMassMode=ZPP_Flags.id_GravMassMode_FIXED;
        zpp_inner.gravMass=gravMass;
        zpp_inner.invalidate_gravMass();
        return zpp_inner.gravMass;
    }
    public var gravMassScale(flibget_gravMassScale,flibset_gravMassScale):Float;
    inline function flibget_gravMassScale(){
        zpp_inner.validate_gravMassScale();
        if(zpp_inner.shapes.empty()){
            if(zpp_inner.massMode==ZPP_Flags.id_MassMode_DEFAULT&&zpp_inner.gravMassMode!=ZPP_Flags.id_GravMassMode_SCALED)throw "Error: Given current mass/gravMass modes; Body::gravMassScale only makes sense if it contains Shapes";
        }
        return zpp_inner.gravMassScale;
    }
    inline function flibset_gravMassScale(gravMassScale:Float){
        if(({
            #if flash9 var ret:Bool=untyped __global__["isNaN"](gravMassScale);
            ret;
            #else Math.isNaN(gravMassScale);
            #end
        }))throw "Error: gravMassScale cannot be NaN";
        zpp_inner.gravMassMode=ZPP_Flags.id_GravMassMode_SCALED;
        zpp_inner.gravMassScale=gravMassScale;
        zpp_inner.invalidate_gravMassScale();
        return zpp_inner.gravMassScale;
    }
    public var inertiaMode(flibget_inertiaMode,flibset_inertiaMode):InertiaMode;
    inline function flibget_inertiaMode()return[InertiaMode.DEFAULT,InertiaMode.FIXED][zpp_inner.inertiaMode]inline function flibset_inertiaMode(inertiaMode:InertiaMode){
        if(inertiaMode==null)throw "Error: Cannot use null InertiaMode";
        zpp_inner.inertiaMode=inertiaMode==InertiaMode.FIXED?ZPP_Flags.id_InertiaMode_FIXED:ZPP_Flags.id_InertiaMode_DEFAULT;
        zpp_inner.invalidate_inertia();
        return this.inertiaMode;
    }
    public var inertia(flibget_inertia,flibset_inertia):Float;
    inline function flibget_inertia(){
        zpp_inner.validate_inertia();
        if(zpp_inner.inertiaMode==ZPP_Flags.id_InertiaMode_DEFAULT&&shapes.empty())throw "Error: Given current inertia mode flag, Body::inertia only makes sense if Body contains Shapes";
        return zpp_inner.cinertia;
    }
    inline function flibset_inertia(inertia:Float){
        if(({
            #if flash9 var ret:Bool=untyped __global__["isNaN"](inertia);
            ret;
            #else Math.isNaN(inertia);
            #end
        }))throw "Error: Inertia cannot be NaN";
        if(inertia<=0)throw "Error: Inertia must be strictly positive";
        zpp_inner.inertiaMode=ZPP_Flags.id_InertiaMode_FIXED;
        zpp_inner.cinertia=inertia;
        zpp_inner.invalidate_inertia();
        return zpp_inner.cinertia;
    }
    #if swc@:keep#end public inline function localToWorld(v:Vec2)return relativeToWorld(localToRelative(v))#if swc@:keep#end public inline function worldToLocal(v:Vec2)return relativeToLocal(worldToRelative(v))#if swc@:keep#end public inline function relativeToWorld(v:Vec2){
        if(v==null)throw "Error: Cannot transform null Vec2";
        return new Vec2(v.x+zpp_inner.posx,v.y+zpp_inner.posy);
    }
    #if swc@:keep#end public inline function worldToRelative(v:Vec2){
        if(v==null)throw "Error: Cannot transform null Vec2";
        return new Vec2(v.x-zpp_inner.posx,v.y-zpp_inner.posy);
    }
    #if swc@:keep#end public inline function localToRelative(v:Vec2){
        if(v==null)throw "Error: Cannot transform null Vec2";
        zpp_inner.validate_axis();
        var tempx:Float;
        var tempy:Float;
        {
            tempx=(zpp_inner.axisy*v.x-zpp_inner.axisx*v.y);
            tempy=(v.x*zpp_inner.axisx+v.y*zpp_inner.axisy);
        };
        return new Vec2(tempx,tempy);
    }
    #if swc@:keep#end public inline function relativeToLocal(v:Vec2){
        if(v==null)throw "Error: Cannot transform null Vec2";
        zpp_inner.validate_axis();
        var tempx:Float;
        var tempy:Float;
        {
            tempx=v.x*zpp_inner.axisy+v.y*zpp_inner.axisx;
            tempy=v.y*zpp_inner.axisy-v.x*zpp_inner.axisx;
        };
        return new Vec2(tempx,tempy);
    }
    #if swc@:keep#end public inline function applyLocalForce(force:Vec2,?pos:Vec2){
        {
            var t=(1.0);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"zpp_inner.force"+",in b: "+"force."+",in s: "+"1.0"+")");
                #end
            };
            zpp_inner.forcex+=force.x*t;
            zpp_inner.forcey+=force.y*t;
        };
        if(pos!=null){
            zpp_inner.validate_axis();
            var rx:Float;
            var ry:Float;
            {
                rx=(zpp_inner.axisy*pos.x-zpp_inner.axisx*pos.y);
                ry=(pos.x*zpp_inner.axisx+pos.y*zpp_inner.axisy);
            };
            zpp_inner.torque+=(force.y*rx-force.x*ry);
        }
        if(isDynamic())zpp_inner.invalidate_wake();
    }
    #if swc@:keep#end public inline function applyRelativeForce(force:Vec2,?pos:Vec2){
        {
            var t=(1.0);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"zpp_inner.force"+",in b: "+"force."+",in s: "+"1.0"+")");
                #end
            };
            zpp_inner.forcex+=force.x*t;
            zpp_inner.forcey+=force.y*t;
        };
        if(pos!=null)zpp_inner.torque+=(force.y*pos.x-force.x*pos.y);
        if(isDynamic())zpp_inner.invalidate_wake();
    }
    #if swc@:keep#end public inline function applyWorldForce(force:Vec2,pos:Vec2){
        {
            var t=(1.0);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"zpp_inner.force"+",in b: "+"force."+",in s: "+"1.0"+")");
                #end
            };
            zpp_inner.forcex+=force.x*t;
            zpp_inner.forcey+=force.y*t;
        };
        if(pos!=null){
            var rx:Float;
            var ry:Float;
            {
                rx=pos.x-zpp_inner.posx;
                ry=pos.y-zpp_inner.posy;
            };
            zpp_inner.torque+=(force.y*rx-force.x*ry);
        }
        if(isDynamic())zpp_inner.invalidate_wake();
    }
    #if swc@:keep#end public inline function applyLocalImpulse(impulse:Vec2,?pos:Vec2){
        {
            var t=(zpp_inner.imass);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"zpp_inner.vel"+",in b: "+"impulse."+",in s: "+"zpp_inner.imass"+")");
                #end
            };
            zpp_inner.velx+=impulse.x*t;
            zpp_inner.vely+=impulse.y*t;
        };
        if(pos!=null){
            zpp_inner.validate_axis();
            var rx:Float;
            var ry:Float;
            {
                rx=(zpp_inner.axisy*pos.x-zpp_inner.axisx*pos.y);
                ry=(pos.x*zpp_inner.axisx+pos.y*zpp_inner.axisy);
            };
            zpp_inner.angvel+=(impulse.y*rx-impulse.x*ry)*zpp_inner.imass;
        }
        if(isDynamic())zpp_inner.invalidate_wake();
    }
    #if swc@:keep#end public inline function applyRelativeImpulse(impulse:Vec2,?pos:Vec2){
        {
            var t=(zpp_inner.imass);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"zpp_inner.vel"+",in b: "+"impulse."+",in s: "+"zpp_inner.imass"+")");
                #end
            };
            zpp_inner.velx+=impulse.x*t;
            zpp_inner.vely+=impulse.y*t;
        };
        if(pos!=null)zpp_inner.angvel+=(impulse.y*pos.x-impulse.x*pos.y)*zpp_inner.imass;
        if(isDynamic())zpp_inner.invalidate_wake();
    }
    #if swc@:keep#end public inline function applyWorldImpulse(impulse:Vec2,pos:Vec2){
        {
            var t=(zpp_inner.imass);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_addeq(in a: "+"zpp_inner.vel"+",in b: "+"impulse."+",in s: "+"zpp_inner.imass"+")");
                #end
            };
            zpp_inner.velx+=impulse.x*t;
            zpp_inner.vely+=impulse.y*t;
        };
        if(pos!=null){
            var rx:Float;
            var ry:Float;
            {
                rx=pos.x-zpp_inner.posx;
                ry=pos.y-zpp_inner.posy;
            };
            zpp_inner.angvel+=(impulse.y*rx-impulse.x*ry)*zpp_inner.imass;
        }
        if(isDynamic())zpp_inner.invalidate_wake();
    }
    #if swc@:keep#end public inline function translateShapes(displacement:Vec2){
        {
            var cx_ite=zpp_inner.shapes.begin();
            while(cx_ite!=null){
                var s=cx_ite.elem();
                s.outer.translate(displacement);
                cx_ite=cx_ite.next;
            }
        };
    }
    #if swc@:keep#end public inline function rotateShapes(angle:Float){
        {
            var cx_ite=zpp_inner.shapes.begin();
            while(cx_ite!=null){
                var s=cx_ite.elem();
                s.outer.rotate(angle);
                cx_ite=cx_ite.next;
            }
        };
    }
    #if swc@:keep#end public inline function scaleShapes(scalex:Float,scaley:Float){
        {
            var cx_ite=zpp_inner.shapes.begin();
            while(cx_ite!=null){
                var s=cx_ite.elem();
                s.outer.scale(scalex,scaley);
                cx_ite=cx_ite.next;
            }
        };
    }
    #if swc@:keep#end public inline function transformShapes(matrix:Mat23){
        {
            var cx_ite=zpp_inner.shapes.begin();
            while(cx_ite!=null){
                var s=cx_ite.elem();
                s.outer.transform(matrix);
                cx_ite=cx_ite.next;
            }
        };
    }
    #if swc@:keep#end public inline function align(){
        if(zpp_inner.shapes.empty())throw "Error: Cannot align empty Body";
        zpp_inner.validate_localCOM();
        var dx=new Vec2(-zpp_inner.localCOMx,-zpp_inner.localCOMy);
        translateShapes(dx);
        dx=localToRelative(dx);
        position.subeq(dx);
        if(zpp_inner.pre_posx!=ZPP_Const.POSINF){
            var t=(1.0);
            {
                #if NAPE_ASSERT var res={
                    !({
                        #if flash9 var ret:Bool=untyped __global__["isNaN"](t);
                        ret;
                        #else Math.isNaN(t);
                        #end
                    });
                };
                if(!res)throw "assert("+"!assert_isNaN(t)"+") :: "+("vec_subeq(in a: "+"zpp_inner.pre_pos"+",in b: "+"dx."+",in s: "+"1.0"+")");
                #end
            };
            zpp_inner.pre_posx-=dx.x*t;
            zpp_inner.pre_posy-=dx.y*t;
        };
    }
    #if swc@:keep#end public inline function setShapeMaterials(material:Material){
        {
            var cx_ite=zpp_inner.shapes.begin();
            while(cx_ite!=null){
                var s=cx_ite.elem();
                s.outer.material=(material.shared?material:material.copy());
                cx_ite=cx_ite.next;
            }
        };
    }
    #if swc@:keep#end public inline function setShapeFilters(filter:InteractionFilter){
        {
            var cx_ite=zpp_inner.shapes.begin();
            while(cx_ite!=null){
                var s=cx_ite.elem();
                s.outer.filter=(filter.shared?filter:filter.copy());
                cx_ite=cx_ite.next;
            }
        };
    }
    #if swc@:keep#end public inline function setShapeFluidProperties(fluidProperties:FluidProperties){
        {
            var cx_ite=zpp_inner.shapes.begin();
            while(cx_ite!=null){
                var s=cx_ite.elem();
                s.outer.fluidProperties=(fluidProperties.shared?fluidProperties:fluidProperties.copy());
                cx_ite=cx_ite.next;
            }
        };
    }
    public var localCOM(flibget_localCOM,never):Vec2;
    inline function flibget_localCOM(){
        if(zpp_inner.wrap_localCOM==null){
            zpp_inner.wrap_localCOM=new Vec2(zpp_inner.localCOMx,zpp_inner.localCOMy);
            zpp_inner.wrap_localCOM.zpp_inner.inuse=true;
            zpp_inner.wrap_localCOM.zpp_inner.immutable=true;
            zpp_inner.wrap_localCOM.zpp_inner._validate=zpp_inner.getlocalCOM;
        }
        return zpp_inner.wrap_localCOM;
    }
    public var worldCOM(flibget_worldCOM,never):Vec2;
    inline function flibget_worldCOM(){
        if(zpp_inner.wrap_worldCOM==null){
            zpp_inner.wrap_worldCOM=new Vec2(zpp_inner.worldCOMx,zpp_inner.worldCOMy);
            zpp_inner.wrap_worldCOM.zpp_inner.inuse=true;
            zpp_inner.wrap_worldCOM.zpp_inner.immutable=true;
            zpp_inner.wrap_worldCOM.zpp_inner._validate=zpp_inner.getworldCOM;
        }
        return zpp_inner.wrap_worldCOM;
    }
    @:keep public inline function toString(){
        return "("+(isDynamic()?"dynamic":isStatic()?"static":"kinematic")+")#"+id;
    }
}
